﻿/*!	@file	r_util_singleton.h
	@brief	シングルトンパターンテンプレート
Copyright (c) 2009 Yuya Yamaguchi

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef _R_UTILE_SINGLETON_H_
#define _R_UTILE_SINGLETON_H_

//! オリジナルのクラスにインターフェースを追加することなくシングルトン機能を追加します
/*! シングルトン生成パターンを適応します。
該当クラスのヘッダにRSINGLETON_DECLARE(className)マクロを記述する事で該当クラスのインスタンスを作成するクラスが宣言されます。
また該当クラスはシングルトン化するに当りコンストラクタをprotectedに宣言して下さい。

@brief	className::instance instanceName;といった形で唯一のインスタンスを定義出来ます。
*/
template<class _T>
class r_tm_singleton
{
public:
	//! コンストラクタ
	/***/
	r_tm_singleton() : instance ( getInstance() ) {}
	//! デストラクタ
	/***/
	~r_tm_singleton() {}
	//! インスタンスへのアクセス
	/***/
	inline _T*			operator -> () {
		return instance;
	}
	inline const _T*	operator -> () const {
		return instance;
	}
	inline _T&			operator() () {
		return *instance;
	}
	inline const _T&	operator() () const {
		return *instance;
	}
private:
	_T*					instance;
	//! 唯一のインスタンスを生成する
	inline	static _T*	getInstance ( void );
};

template<class _T> _T* r_tm_singleton<_T> :: getInstance ( void )
{
	static _T	_instance;
	return &_instance;
}

//! .hのクラス宣言内に記述
#define RSINGLETON_DECLARE(className)		private:\
											friend class r_tm_singleton<className>;\
											className(const className& src);\
											const className& operator = (const className& src);\
											public:\
											typedef r_tm_singleton<className> instance;


//! 上記シングルトンと同じインターフェースを継承クラスを返す実装です
/*!
*/
template<class _T>
class r_tm_singletonGetInterface
{
public:
	//! コンストラクタ
	/***/
	r_tm_singletonGetInterface() {}
	//! デストラクタ
	/***/
	~r_tm_singletonGetInterface() {}
	//! インスタンスへのアクセス
	/***/
	inline _T*			operator -> () {
		return typename _T::getInstance();
	}
	inline const _T*	operator -> () const {
		return typename _T::getInstance();
	}
	inline _T&			operator() () {
		return * ( typename _T::getInstance() );
	}
	inline const _T&	operator() () const {
		return * ( typename _T::getInstance() );
	}
};


//! .hのクラス宣言内に記述
#define RSINGLETONTGET_DECLARE(className)	private:\
											friend class r_tm_singletonGetInterface<className>;			\
											className(const className& src);							\
											const className& operator = (const className& src);			\
											static	className*			_this;							\
											public:														\
											typedef r_tm_singletonGetInterface<className> instance;		\
											static	void				create();						\
											static	void				destroy();						\
											static	className*			getInstance(){return _this;}


//! .cppに記述
#define RSINGLETONGET_IMPLEMENT(className, createClassName)		\
className*	className :: _this = NULL;							\
void		className :: create()								\
{																\
	_this = new createClassName();								\
}																\
void		className :: destroy()								\
{																\
	delete _this;												\
	_this = NULL;												\
}


#endif // _R_UTILE_SINGLETON_H_
